package com.example.demo.service.shop;

import com.alibaba.fastjson.JSONObject;
import com.example.demo.entity.Cart;
import com.example.demo.entity.Product;
import com.example.demo.repository.CartRepository;
import com.example.demo.util.CartCacheObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * Copyright (C), 2019-2019, XXX有限公司
 * FileName: CartServiceImpl
 * Author:   longzhonghua
 * Date:     2019/4/13 12:34
 *
 * @Description: $description$
 * History:
 * <author>          <time>          <version>          <desc>
 * 作者姓名           修改时间           版本号              描述
 */
@Service
//@CacheConfig(cacheNames = "cart")
public class CartServiceImpl implements CartService {
    /**
     * 购物车缓存key（冒号后面接用户id）
     * zset类型，value为购物车缓存条目对象
     */
    public static final String CART_KEY = "cart:";
    @Autowired
    private CartRepository cartRepository;
    @Autowired
    private RedisTemplate redisTemplate;
    @Resource
    private ProductService productService;
    @Override
    public List<Cart> getCartList() {
        return cartRepository.findAll();
    }

    @Override
    public Cart findCartById(long id) {
        return cartRepository.findByid(id);
    }

    /**
     * 查找指定用户的购物车
     * @param userId
     * @return
     */
    @Override
    public List<Cart> findCartByIdNative(Long userId) {
        List<Cart> cartList = null;
        String key = CART_KEY + userId;
        //直接访问购物车或缓存已经过期，
        if(!redisTemplate.hasKey(key)) {
            //查询数据库是否有该用户以前的购物车记录，有则加入到该用户的缓存中
            cartList = loadCartListAndCached(userId);
        } else {
            //从缓存中取
            cartList = new ArrayList<>();
            Set<String> values = redisTemplate.opsForHash().keys(key);
            for (String productIdKey : values) {
                String jsonString = (String) redisTemplate.opsForHash().get(key,productIdKey);
                CartCacheObject cartCacheObject = JSONObject.parseObject(jsonString, CartCacheObject.class);
                cartList.add(cartCacheObject.toCart());
            }
        }
        return cartList;
    }

    @Override
    public void save(Cart cart) {
        Product product = productService.findByid(cart.getProduct_id());
        if(cart.getProduct_num()==null) cart.setProduct_num(1L);
        cart.setProduct_name(product.getName());
        cart.setProduct_price(product.getPrice());
        cart.setCreateTime(System.currentTimeMillis());
        Cart existsItem = cartRepository.findByUserIdAndProductId(cart.getUser_id(),cart.getProduct_id());
        if(existsItem!=null) {
            existsItem.setProduct_num(existsItem.getProduct_num() + cart.getProduct_num());
            existsItem.setProduct_price(product.getPrice());
            existsItem.setUpdateTime(System.currentTimeMillis());
            //修改
            cartRepository.save(existsItem);
            cart = existsItem;
        } else {
            //保存数据到db
            cartRepository.save(cart);
        }

        //第一次添加商品购物车或缓存已经过期，缓存中没有该用户的购物车
        if(!redisTemplate.hasKey(CART_KEY + cart.getUser_id())) {
            //查询数据库是否有该用户以前的购物车记录，有则加入到该用户的缓存中
            loadCartListAndCached(cart.getUser_id());
        }
        //添加新添加的购物车商品到缓存中
//        if(existsItem==null) {
            addToCache(cart);
//        }
    }

    private List<Cart> loadCartListAndCached(Long userId) {
        List<Cart> cartList = cartRepository.findCartByIdNative(userId);
        for (Cart dbCart : cartList) {
            addToCache(dbCart);
        }
        return cartList;
    }

    private void addToCache(Cart cart) {
        String key = CART_KEY + cart.getUser_id();
//        redisTemplate.opsForZSet().add(key, JSONObject.toJSONString(CartCacheObject.convert(cart)),System.currentTimeMillis());
        redisTemplate.opsForHash().put(key,cart.getProduct_id().toString(),JSONObject.toJSONString(CartCacheObject.convert(cart)));
        //为了演示方便，过期时间设置为2分钟，实际项目可以设置更长时间
        redisTemplate.expire(key,2, TimeUnit.MINUTES);
    }


}
